﻿using Microsoft.Xna.Framework;

namespace XnaPathfidingLibrary
{
    /// <summary>
    /// This class defines a map node.
    /// </summary>
    public class MapNode
    {
        /// <summary>
        /// Defines if the node is navigable. Non navigable nodes are not taken into account when making the search path.
        /// </summary>
        private bool navigable;

        /// <summary>
        /// Defines if the node has been visited.
        /// </summary>
        private bool visited;

        /// <summary>
        /// Defines if the node has been added to a wait list.
        /// </summary>
        private bool added;

        /// <summary>
        /// Node position in the map matrix. 
        /// This is an index position in the matrix, not it's absolute position in the world.
        /// </summary>
        private Point position;

        /// <summary>
        /// The previous node in the current path this node is part of.
        /// </summary>
        private MapNode parent;

        /// <summary>
        /// Accumulated since the start node to this node.
        /// </summary>
        private int totalCost;

        /// <summary>
        /// Heuristic cost used for A* search.
        /// </summary>
        private int heuristicCost;

        /// <summary>
        /// Node cost used for A* cost. 
        /// It means the cost for going from a neightbor node to this one.
        /// </summary>
        private int nodeCost;

        /// <summary>
        /// Custom data that could be attached to the node.
        /// Any kind of data can be stored in this field.
        /// </summary>
        private object data;


        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>        
        /// <param name="navigable">If the node is navigable or not.</param>
        /// <param name="position">Node position.</param>
        public MapNode(bool navigable, Point position)
        {
            this.navigable = navigable;
            this.position = position;
            this.visited = false;
            this.added = false;
            this.parent = null;
            this.totalCost = 0;
            this.heuristicCost = 0;
            this.nodeCost = 0;
        }

        /// <summary>
        /// Gets the node position.
        /// </summary>
        public Point Position
        {
            get { return position; }
        }

        /// <summary>
        /// Gets or sets node's navigability.
        /// </summary>
        public bool Navigable
        {
            get { return navigable; }
            set { navigable = value;}
        }

        /// <summary>
        /// Defines if the node has been visited.
        /// </summary>
        public bool Visited
        {
            get { return visited; }
            set { visited = value; }
        }

        /// <summary>
        /// Defines if the node has been added to the wait list.
        /// </summary>
        public bool Added
        {
            get { return added; }
            set { added = value; }
        }

        /// <summary>
        /// Gets or sets node's parent.
        /// </summary>
        public MapNode Parent
        {
            get { return parent; }
            set { parent = value; }
        }

        /// <summary>
        /// Gets or sets node's total cost.
        /// </summary>
        public int TotalCost
        {
            get { return totalCost; }
            set { totalCost = value; }
        }

        /// <summary>
        /// Gets or sets node's heuristic cost.
        /// </summary>
        public int HeuristicCost
        {
            get { return heuristicCost; }
            set { heuristicCost = value; }
        }

        /// <summary>
        /// Gets or sets node's cost.
        /// </summary>
        public int NodeCost
        {
            get { return nodeCost; }
            set { nodeCost = value; }
        }

        /// <summary>
        /// Gets or sets node's data.
        /// Any kind of data can be stored within this field (a class, a struct, an enum...).
        /// </summary>
        public object Data
        {
            get { return data; }
            set { data = value; }
        }
    }
}
